/**
 * MessageDispatcher.java
 * ************************** 
 * @date Mar 22, 2011
 * @author Michele Tamburini
 * 
 * **************************
 */
package networkRmi;


import java.util.Deque;
import java.util.Queue;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

import messages.Message;
import messages.MessageHandler;

/**
 * Description: The MessageDispatcher contains pointers to all the MessageHandlers registered by services. Once the CommunicationServer deposits Messages into the 'receivedMessages' list,  it moves them to a new one: 'messagesToDispatch'.  Then it scans the 'messageToDispatch' list through all the registered MessageHandlers, in order to  find the service to which a Message belongs.
 * @uml.dependency   supplier="messages.MessageHandler"
 */
public class MessageDispatcher extends Thread {
	
	public static String MESSAGE_DISPATCHER_THREAD = "MessageDispatcherThread"; 
	
	private Deque<Message> receivedMessages ;
	private Queue<Message> messagesToDispatch ;
	
	private Vector<MessageHandler> registeredHandlers = new Vector<MessageHandler>();
	
	private boolean hasToStop;
	
	private Logger log = Logger.getLogger("MsgDispatcher_log");
	
	public MessageDispatcher(Deque<Message> receivedMessages,
			Queue<Message> messagesToDispatch) {
		this.receivedMessages = receivedMessages;
		this.messagesToDispatch = messagesToDispatch;
		setName(MESSAGE_DISPATCHER_THREAD);
		log.setLevel(Level.OFF);
	}

	public void run(){
		boolean running = true;
		log.info("Started msg dispathcer");
		while(running){
			try {
				if(!this.isInterrupted())
				synchronized (receivedMessages) {
					receivedMessages.wait(0);
					log.info(Thread.currentThread().getName()+"dispatching messages");
					while(!receivedMessages.isEmpty()){
						messagesToDispatch.add(receivedMessages.pollFirst());
					}
					receivedMessages.notify();
				}
			} catch (InterruptedException e) {
				//				e.printStackTrace();
				if(hasToStop){
					running = false;
					System.out.println(getName()+ " I'm interrupted");
				}
			}
			
			/*here must executes the handler queue in order to find 
			for each message its own handler (and yet ServiceLevel to which
			deliver the message*/
			
			//bad implementation with N^2 steps:
			for(MessageHandler handler : registeredHandlers){
				handler.extractIncomingMessages(messagesToDispatch);
			}
		}
	}
	
	public void stopMessageDispatcher(){
		hasToStop = true;
		this.interrupt();
	}
	
	public boolean register(MessageHandler msgHand){
		return registeredHandlers.add(msgHand);
	}
	
	public boolean deRegister(MessageHandler msgHand){
		return registeredHandlers.remove(msgHand);
	}
	

}
